In [12]:
library(rstatix)
library(dplyr) 
library(ggplot2) 

# A small function helping us to round  all numbers (0.123456 -> 0.123)
round_df <- function(df, digits = 3) {
    nums <- vapply(df, is.numeric, FUN.VALUE = logical(1))
    df[,nums] <- round(df[,nums], digits = digits)
    (df)
}

# Loading the CSV file
df <- read.csv("data-wpm-threefactorial.csv")

# Show header if everything is OK
head(df)

# Check if data is normal distributed
round_df(df %>% group_by(Swipe, Visual, Tactile) %>% shapiro_test(WPM))

# Nothing is significant, so we can run a three-way repeated-measures ANOVA
anova <- anova_test(data = df, dv = WPM, wid = SubjectID, within = c(Swipe, Visual, Tactile), effect.size = "pes")

# Auto correction of degree of freedom (if necessary)
get_anova_table(anova, correction = "auto")  

# Let's aggregate the data
means <- df %>% group_by(Swipe,Tactile, Visual) %>% summarize(
    Mean = mean(WPM),
    SD = sd(WPM),
    N = n(), .groups = 'drop',) %>% mutate(
    SE = SD / sqrt(N),
    CI = qt(1 - (0.05 / 2), N - 1) * SE) 

# Let's plot the data
plot <- ggplot(means, aes(y=Mean, x=Visual, fill=Swipe)) +  
                    geom_bar(stat = "identity", position = position_dodge(width = 0.8), width=0.75) + 
                    geom_errorbar(aes(ymin=Mean-CI, ymax=Mean+CI, width=.1), position=position_dodge(0.8), width=0.2, size=0.3) + 
                    ylab("words per minute") + 
                    xlab("")+
                    ggtitle("Typing performance in words per minute (WPM)") +
                    theme_minimal() +
                    facet_wrap(Tactile~.) +
                    scale_fill_manual(values = c("tomato1","steelblue2","gold2", "olivedrab3", "gray70")) + 
                    theme(
                        legend.margin=margin(t = -5, unit='mm'),
                        plot.margin=unit(x=c(1,2,1,1),units="mm"),
                        legend.position = "bottom",
                        legend.title = element_blank(),
                        plot.title = element_text(hjust = 0.5), 
                        panel.background = element_rect(size=0.5, color="transparent", fill="gray98" )
                    ) 

options(repr.plot.width = 6, repr.plot.height = 4)
plot 
ggsave("Swipe-Modality-BarChart.pdf", plot, width=5, height=3.5, device=cairo_pdf)
A data.frame: 6 × 5
SubjectIDSwipeVisualTactileWPM
<int><chr><chr><chr><dbl>
11No SwipeNo Visual FeedbackNo Tactile Feedback31.36881
21Swipe No Visual FeedbackNo Tactile Feedback45.19973
31No SwipeVisual Feedback No Tactile Feedback46.75281
41Swipe Visual Feedback No Tactile Feedback62.19684
51No SwipeNo Visual FeedbackTactile Feedback 39.96038
61Swipe No Visual FeedbackTactile Feedback 43.49072
A tibble: 8 × 6
SwipeVisualTactilevariablestatisticp
<chr><chr><chr><chr><dbl><dbl>
No SwipeNo Visual FeedbackNo Tactile FeedbackWPM0.9670.424
No SwipeNo Visual FeedbackTactile Feedback WPM0.9840.904
No SwipeVisual Feedback No Tactile FeedbackWPM0.9740.624
No SwipeVisual Feedback Tactile Feedback WPM0.9810.828
Swipe No Visual FeedbackNo Tactile FeedbackWPM0.9810.817
Swipe No Visual FeedbackTactile Feedback WPM0.9880.976
Swipe Visual Feedback No Tactile FeedbackWPM0.9580.248
Swipe Visual Feedback Tactile Feedback WPM0.9780.725
A anova_test: 7 × 7
EffectDFnDFdFpp<.05pes
<chr><dbl><dbl><dbl><dbl><chr><dbl>
1Swipe 131 52.7553.59e-08*0.630
2Visual 131323.9815.74e-18*0.913
3Tactile 131 0.8823.55e-01 0.028
4Swipe:Visual 131 0.6454.28e-01 0.020
5Swipe:Tactile 131 8.7286.00e-03*0.220
6Visual:Tactile 131 2.2951.40e-01 0.069
7Swipe:Visual:Tactile131 0.5284.73e-01 0.017
In [14]:
# Execute code above first

# Loading the CSV file with the TLX subscores
df <- read.csv("data-tlx-threefactorial.csv")

# TLX = Mental Demand + Phyiscal Demand + Temporal Demand + Performance + Effort + Frustration
df$TLX <- df$MD + df$PD + df$TD + df$PE + df$EF + df$FR

# Check the head
head(df)

# Check if data is normal distributed
round_df(df %>% group_by(Swipe, Visual, Tactile) %>% shapiro_test(TLX))

# One is significant, however, we still assume normality and run a three-way repeated-measures ANOVA
anova <- anova_test(data = df, dv = TLX, wid = SubjectID, within = c(Swipe, Visual, Tactile), effect.size = "pes")

# Auto correction of degree of freedom (if necessary)
get_anova_table(anova, correction = "auto")  

# Let's aggregate the data
means <- df %>% group_by(Swipe,Tactile, Visual) %>% summarize(
    Mean = mean(TLX),
    SD = sd(TLX),
    N = n(), .groups = 'drop',) %>% mutate(
    SE = SD / sqrt(N),
    CI = qt(1 - (0.05 / 2), N - 1) * SE) 

# Let's plot the data
plot <- ggplot(means, aes(y=Mean, x=Visual, fill=Swipe)) +  
                    geom_bar(stat = "identity", position = position_dodge(width = 0.8), width=0.75) + 
                    geom_errorbar(aes(ymin=Mean-CI, ymax=Mean+CI, width=.1), position=position_dodge(0.8), width=0.2, size=0.3) + 
                    ylab("score") + 
                    xlab("")+
                    ggtitle("Workload (RTLX)") +
                    theme_minimal() +
                    facet_wrap(Tactile~.) +
                    scale_fill_manual(values = c("tomato1","steelblue2","gold2", "olivedrab3", "gray70")) + 
                    theme(
                        legend.margin=margin(t = -5, unit='mm'),
                        plot.margin=unit(x=c(1,2,1,1),units="mm"),
                        legend.position = "bottom",
                        legend.title = element_blank(),
                        plot.title = element_text(hjust = 0.5), 
                        panel.background = element_rect(size=0.5, color="transparent", fill="gray98" )
                    ) 

options(repr.plot.width = 6, repr.plot.height = 4)
plot 
ggsave("Swipe-Modality-BarChart.pdf", plot, width=5, height=3.5, device=cairo_pdf)
A data.frame: 6 × 12
SubjectIDSequenceSwipeVisualTactileMDPDTDPEEFFRTLX
<int><int><chr><chr><chr><int><int><int><int><int><int><int>
111No SwipeNo Visual FeedbackNo Tactile Feedback 0 3 609523
212Swipe No Visual FeedbackNo Tactile Feedback 214 770434
313Swipe Visual Feedback Tactile Feedback 10101086650
414No SwipeVisual Feedback No Tactile Feedback 7 2 340622
515No SwipeVisual Feedback Tactile Feedback 4 8 163729
616Swipe Visual Feedback No Tactile Feedback 5 9 146328
A tibble: 8 × 6
SwipeVisualTactilevariablestatisticp
<chr><chr><chr><chr><dbl><dbl>
No SwipeNo Visual FeedbackNo Tactile FeedbackTLX0.9640.359
No SwipeNo Visual FeedbackTactile Feedback TLX0.9610.294
No SwipeVisual Feedback No Tactile FeedbackTLX0.9840.898
No SwipeVisual Feedback Tactile Feedback TLX0.9860.951
Swipe No Visual FeedbackNo Tactile FeedbackTLX0.9260.031
Swipe No Visual FeedbackTactile Feedback TLX0.9790.783
Swipe Visual Feedback No Tactile FeedbackTLX0.9680.439
Swipe Visual Feedback Tactile Feedback TLX0.9710.530
A anova_test: 7 × 7
EffectDFnDFdFpp<.05pes
<chr><dbl><dbl><dbl><dbl><chr><dbl>
1Swipe 131137.5406.25e-13*0.816
2Visual 131 4.3514.50e-02*0.123
3Tactile 131 63.5895.29e-09*0.672
4Swipe:Visual 131 1.0693.09e-01 0.033
5Swipe:Tactile 131 15.0025.19e-04*0.326
6Visual:Tactile 131 29.1586.82e-06*0.485
7Swipe:Visual:Tactile131 3.9935.50e-02 0.114
In [ ]: